﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.IO;
using System.Configuration;
using System.Security.Cryptography;

namespace CNdotnet.Ezsocio.Core.Security
{
    public class SymmetricAlgorithmProvider<T> : ICryptographyProvider where T: SymmetricAlgorithm, new()
    {
        #region Private Fields

        private T provider = new T();

        //TODO: Consider about how to get Keys and IVs
        private byte[] bKeys = Encoding.ASCII.GetBytes("ucenter1");
        private byte[] bIVs = Encoding.ASCII.GetBytes("ucenter1");

        #endregion

        #region Constructor

        public SymmetricAlgorithmProvider()
        {
            //Init();
            //bKeys = provider.Key;
            //bIVs = provider.IV;
        }

        public SymmetricAlgorithmProvider(byte[] keys, byte[] ivs)
        {
            bKeys = keys;
            bIVs = ivs;
        }

        #endregion

        #region Public Properties

        public byte[] Keys
        {
            get { return bKeys; }
            set { bKeys = value; }
        }
        public byte[] IVs 
        {
            get { return bIVs; }
            set { bIVs = value; }
        }

        #endregion

        #region Public Methods

        public string Encrypting(string source)
        {
            return Encrypting(source, Keys, IVs);
        }

        public string Decrypting(string source)
        {
            return Decrypting(source, Keys, IVs);
        }

        public string Encrypting(string source, byte[] keys, byte[] ivs)
        {
            byte[] bEncrypted = CryptoTransform(provider.CreateEncryptor(keys, ivs),
                Encoding.UTF8.GetBytes(source));

            return Convert.ToBase64String(bEncrypted);
        }

        public string Decrypting(string source, byte[] keys, byte[] ivs)
        {
            byte[] bDecrypted = CryptoTransform(provider.CreateDecryptor(keys, ivs),
                Convert.FromBase64String(source));

            return Encoding.UTF8.GetString(bDecrypted);
        }

        #endregion

        #region Private Methods

        private byte[] CryptoTransform(ICryptoTransform cryptoTransform, byte[] bSrcs)
        {
            MemoryStream ms = new MemoryStream();
            CryptoStream cs = new CryptoStream(ms, cryptoTransform, CryptoStreamMode.Write);

            try
            {
                cs.Write(bSrcs, 0, bSrcs.Length);
                cs.FlushFinalBlock();

                ms.Position = 0;
            }
            catch (CryptographicException )
            {
                //TODO: Unify exception handler here
            }
            finally
            {
                ms.Close();
                cs.Close();
            }

            return ms.ToArray();
        }

        private void Init()
        {
            provider.GenerateKey();
            provider.GenerateIV();
        }

        #endregion
    }
}
